using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Threading;

namespace ClownFish
{
	public static class BuildManager
	{
		[CompilerGenerated]
		private sealed class Class3
		{
			public Type type_0;

			public bool method_0(Class27 class27_0)
			{
				return class27_0.class26_0.type_0 == this.type_0;
			}
		}

		[CompilerGenerated]
		private sealed class Class4
		{
			public Func<Type, bool> func_0;

			public bool method_0(f__AnonymousType0<Assembly, Type> f__AnonymousType0_0)
			{
				return !f__AnonymousType0_0.Prop_1.IsValueType && !f__AnonymousType0_0.Prop_1.IsInterface && !f__AnonymousType0_0.Prop_1.IsGenericType && !f__AnonymousType0_0.Prop_1.IsAbstract && this.func_0(f__AnonymousType0_0.Prop_1);
			}
		}

		private static BuildExceptionHandler buildExceptionHandler_0;

		private static readonly object object_0 = new object();

		private static Timer timer_0 = null;

		private static Func<bool> func_0 = null;

		private static int int_0 = 0;

		private static Dictionary<Type, int> dictionary_0 = new Dictionary<Type, int>(2048);

		internal static int int_1 = 0;

		[CompilerGenerated]
		private static Func<Type, Type> func_1;

		[CompilerGenerated]
		private static Func<Assembly, IEnumerable<Type>> func_2;

		[CompilerGenerated]
		private static Func<Assembly, Type, f__AnonymousType0<Assembly, Type>> func_3;

		[CompilerGenerated]
		private static Func<f__AnonymousType0<Assembly, Type>, Type> func_4;

		public static event BuildExceptionHandler OnBuildException
		{
			[MethodImpl(MethodImplOptions.Synchronized)]
			add
			{
				BuildManager.buildExceptionHandler_0 = (BuildExceptionHandler)Delegate.Combine(BuildManager.buildExceptionHandler_0, value);
			}
			[MethodImpl(MethodImplOptions.Synchronized)]
			remove
			{
				BuildManager.buildExceptionHandler_0 = (BuildExceptionHandler)Delegate.Remove(BuildManager.buildExceptionHandler_0, value);
			}
		}

		public static int RequestCount
		{
			get
			{
				return BuildManager.int_0;
			}
		}

		public static int WaitTypesCount
		{
			get
			{
				int count;
				lock (BuildManager.object_0)
				{
					count = BuildManager.dictionary_0.Count;
				}
				return count;
			}
		}

		internal static void smethod_0(Type type_0)
		{
			if (!type_0.IsValueType && !type_0.IsGenericType && !type_0.IsInterface && !type_0.IsAbstract)
			{
				lock (BuildManager.object_0)
				{
					BuildManager.dictionary_0[type_0] = 0;
					BuildManager.int_0++;
				}
				return;
			}
		}

		public static void StartAutoCompile(Func<bool> func)
		{
			BuildManager.StartAutoCompile(func, 5000);
		}

		public static void StartAutoCompile(Func<bool> func, int timerPeriod)
		{
			if (func == null)
			{
				throw new ArgumentNullException("func");
			}
			if (timerPeriod < 3000)
			{
				throw new ArgumentOutOfRangeException("timerPeriod", "timerPeriod must more than 3000");
			}
			int num = Interlocked.CompareExchange(ref BuildManager.int_1, 1, 0);
			if (num == 1)
			{
				throw new InvalidOperationException("已经开启过自动编译模式。");
			}
			BuildManager.func_0 = func;
			BuildManager.timer_0 = new Timer(new TimerCallback(BuildManager.smethod_1), null, timerPeriod, timerPeriod);
		}

		private static void smethod_1(object object_1)
		{
			if (!BuildManager.func_0())
			{
				return;
			}
			if (BuildManager.int_0 == 0)
			{
				return;
			}
			Type[] array = null;
			lock (BuildManager.object_0)
			{
				IEnumerable<Type> arg_4A_0 = BuildManager.dictionary_0.Keys;
				if (BuildManager.func_1 == null)
				{
					BuildManager.func_1 = new Func<Type, Type>(BuildManager.smethod_4);
				}
				array = arg_4A_0.Select(BuildManager.func_1).ToArray<Type>();
				BuildManager.dictionary_0.Clear();
				BuildManager.int_0 = 0;
			}
			if (array != null && array.Length != 0)
			{
				BuildManager.CompileModelTypesAsync(array);
				return;
			}
		}

		public static void CompileModelTypesSync(Type[] types, bool throwOnFailure)
		{
			if (throwOnFailure)
			{
				BuildManager.smethod_3(types);
				return;
			}
			try
			{
				BuildManager.smethod_3(types);
			}
			catch (Exception exception_)
			{
				BuildExceptionHandler buildExceptionHandler = BuildManager.buildExceptionHandler_0;
				if (buildExceptionHandler != null)
				{
					try
					{
						buildExceptionHandler(exception_);
					}
					catch
					{
					}
				}
			}
		}

		public static void CompileModelTypesAsync(Type[] types)
		{
			ThreadPool.QueueUserWorkItem(new WaitCallback(BuildManager.smethod_2), types);
		}

		private static void smethod_2(object object_1)
		{
			Type[] types = (Type[])object_1;
			BuildManager.CompileModelTypesSync(types, false);
		}

		private static void smethod_3(Type[] type_0)
		{
			if (type_0 == null || type_0.Length == 0)
			{
				return;
			}
			List<Type> list = new List<Type>(type_0.Length);
			for (int i = 0; i < type_0.Length; i++)
			{
				Type type = type_0[i];
				Class6 @class = type.smethod_0(false);
				if (@class.method_13(Enum0.const_0, Enum0.const_1))
				{
					list.Add(type);
				}
			}
			if (list.Count == 0)
			{
				return;
			}
			List<Class27> list2 = Class28.smethod_19(list);
			Assembly assembly = Class32.smethod_1(list2);
			using (List<Type>.Enumerator enumerator = list.GetEnumerator())
			{
				Func<Class27, bool> func = null;
				BuildManager.Class3 class2 = new BuildManager.Class3();
				while (enumerator.MoveNext())
				{
					class2.type_0 = enumerator.Current;
					Class6 class3 = class2.type_0.smethod_0(false);
					IEnumerable<Class27> arg_AA_0 = list2;
					if (func == null)
					{
						func = new Func<Class27, bool>(class2.method_0);
					}
					Class27 class4 = arg_AA_0.First(func);
					Type type2 = assembly.GetType(Class28.string_0 + "." + class4.class26_0.string_1);
					MethodInfo method = type2.GetMethod(class4.class26_0.string_2);
					MethodInfo method2 = type2.GetMethod(class4.class26_0.string_3);
					MethodInfo method3 = type2.GetMethod(class4.class26_0.string_4);
					Delegate0 delegate0_ = (Delegate0)Delegate.CreateDelegate(typeof(Delegate0), null, method, true);
					Delegate1 delegate1_ = (Delegate1)Delegate.CreateDelegate(typeof(Delegate1), null, method2, true);
					Delegate2 delegate2_ = (Delegate2)Delegate.CreateDelegate(typeof(Delegate2), null, method3, true);
					class3.method_7(delegate0_, delegate1_, delegate2_);
				}
			}
		}

		public static Type[] FindModelTypesFromCurrentApplication(Func<Type, bool> predicate)
		{
			Assembly[] assemblies = Class29.smethod_0();
			return BuildManager.FindModelTypes(predicate, assemblies);
		}

		public static Type[] FindModelTypes(Func<Type, bool> predicate, params Assembly[] assemblies)
		{
			BuildManager.Class4 @class = new BuildManager.Class4();
			@class.func_0 = predicate;
			if (@class.func_0 == null)
			{
				throw new ArgumentNullException("predicate");
			}
			if (assemblies != null && assemblies.Length != 0)
			{
				if (BuildManager.func_2 == null)
				{
					BuildManager.func_2 = new Func<Assembly, IEnumerable<Type>>(BuildManager.smethod_5);
				}
				Func<Assembly, IEnumerable<Type>> arg_63_1 = BuildManager.func_2;
				if (BuildManager.func_3 == null)
				{
					BuildManager.func_3 = new Func<Assembly, Type, f__AnonymousType0<Assembly, Type>>(BuildManager.smethod_6);
				}
				var arg_A3_0 = assemblies.SelectMany(arg_63_1, BuildManager.func_3).Where(new Func<f__AnonymousType0<Assembly, Type>, bool>(@class.method_0));
				if (BuildManager.func_4 == null)
				{
					BuildManager.func_4 = new Func<f__AnonymousType0<Assembly, Type>, Type>(BuildManager.smethod_7);
				}
				return arg_A3_0.Select(BuildManager.func_4).ToArray<Type>();
			}
			throw new ArgumentNullException("array");
		}

		[CompilerGenerated]
		private static Type smethod_4(Type type_0)
		{
			return type_0;
		}

		[CompilerGenerated]
		private static IEnumerable<Type> smethod_5(Assembly assembly_0)
		{
			return assembly_0.GetExportedTypes();
		}

		[CompilerGenerated]
		private static f__AnonymousType0<Assembly, Type> smethod_6(Assembly assembly_0, Type type_0)
		{
			return new f__AnonymousType0<Assembly, Type>
            {
				Prop_2 = assembly_0,
                Prop_1 = type_0
			};
		}

		[CompilerGenerated]
		private static Type smethod_7(f__AnonymousType0<Assembly, Type> f__AnonymousType0_0)
		{
			return f__AnonymousType0_0.Prop_1;
		}
	}
}
